/**
 * @class Spark.ComboBox
 * @extends Spark.TriggerField
 * <p>Combo组件.
 * @author njq.niu@hand-china.com
 * @constructor
 * @param {Object} config 配置对象. 
 */
$S.ComboBox = Ext.extend($S.TriggerField, {	
	maxHeight : 300,
	blankOption : true,
	rendered : false,
	selectedClass : 's_cb_sd',
    overClass: 's_cb_ov',
    initConfig : function(config) {
		$S.ComboBox.superclass.initConfig.call(this, config);
		if (config.options) {
			this.setOptions(config.options);
		} else {
			this.clearOptions();
		}
	},
    initStatus : function(){
        $S.ComboBox.superclass.initStatus.call(this);
        if (this.editable === false && this.disabled == false)
            this.el.dom.readOnly = true;
    },
    processListener: function(ou){
        $S.ComboBox.superclass.processListener.call(this, ou);
        if(this.popup){
            this.popup[ou]('click', this.onViewClick,this);
            this.popup[ou]('mousemove',this.onViewMove,this);
        }
    },
	initEvents:function(){
		$S.ComboBox.superclass.initEvents.call(this);
		this.addEvents(
		/**
         * @event select
         * 选择事件.
         * @param {Spark.Combobox} combo combo对象.
         * @param {Object} value valueField的值.
         * @param {Object} display displayField的值.
         * @param {Spark.Record} record 选中的Record对象
         */
		'select');
	},
	initQuery: function(){//事件定义中调用
		this.doQuery(this.getText());
	},
    initList: function(){
        this.refresh();
        if(this.optionDataSet.loading == true){//TODO:需要测试
            this.view.update('<li>正在加载...</li>');
        }else{
            var datas = this.optionDataSet.getAll(),
                l=datas.length,
                sb = [];
            for(var i=0;i<l;i++){
                var r = datas[i],text = this.getRenderText(r);
                sb.push('<li code="'+r.get(this.valueField)+'">'+text+'</li>');
            }
            if(l!=0){
                this.view.update(sb.join(''));          
            }
        }
        this.correctViewSize();
    },    
    getRecordByDisplay: function(name){
    	if(!this.optionDataSet)return null;
        var record = null;
        Ext.each(this.optionDataSet.getAll(),function(r){
            if(this.getRenderText(r) == name){
                record = r;
                return false;
            }
        },this);
        return record;
    },
	doExpand : function(){
		if(!this.optionDataSet)return;
		if(this.rendered === false)this.initQuery();
		var index = this.getIndex(this.getValue());
		this.clearSelectItem();
        if (index!=-1) {	
            this.selectItem(index);
		}		
		$S.ComboBox.superclass.doExpand.call(this);
	},
	/**
	 * 收起下拉菜单.
	 */
	collapse:function(){
		$S.ComboBox.superclass.collapse.call(this);	
        if(this.optionDataSet)this.optionDataSet.clearFilter();
	},
	clearOptions : function(){
	   this.processDataSet('un');
	   this.optionDataSet = null;
	},
	setOptions : function(name){
		var ds = name
		if(typeof(name)==='string'){
			ds = $(name);
		}
		if(this.optionDataSet != ds){
			this.optionDataSet = ds;
			this.processDataSet('un');
			this.processDataSet('on');
			this.rendered = false;
			if(!Ext.isEmpty(this.value)) this.setValue(this.value, true)
		}
	},
	processDataSet: function(ou){
		if(this.optionDataSet){
            this.optionDataSet[ou]('load', this.onDataSetLoad, this);
            this.optionDataSet[ou]('add', this.onDataSetLoad, this);
            this.optionDataSet[ou]('update', this.onDataSetLoad, this);
            this.optionDataSet[ou]('remove', this.onDataSetLoad, this);
            this.optionDataSet[ou]('clear', this.onDataSetLoad, this);
            this.optionDataSet[ou]('reject', this.onDataSetLoad, this);
		}
	},	
	correctViewSize: function(){
		var widthArray = [],mw = this.wrap.getWidth();
		for(var i=0;i<this.view.dom.childNodes.length;i++){
			var li=this.view.dom.childNodes[i];
			var width=$S.TextMetrics.measure(li.innerHTML).width;
            
			mw = Math.max(mw,width)||mw;
		}
		var lh = Math.min(this.popup.child('ul').getHeight()+2,this.maxHeight); 
        //mw = mw + (( lh < this.maxHeight) ? 10 : 27);//scrollbar
		this.popup.setWidth(mw).setHeight(lh<20?20:lh);
//    	this.shadow.setWidth(mw).setHeight(lh<20?20:lh);
	},
	doQuery : function(q) {
        var ds = this.optionDataSet;
        if(!ds)return;
        if(Ext.isEmpty(q)){
            ds.clearFilter();
        }else {            
            var reg = new RegExp(q.replace(/[+?*.^$\[\](){}\\|]/g,function(v){
                    return '\\'+v;
                }),'i');
            ds.filter(function(r){
                return reg.test(this.getRenderText(r));
            },this);
        }
		this.draw();
	},
    draw:function(){
        if(!this.view){
            this.popup.update('<ul></ul>');
            this.view=this.popup.child('ul');
        }
        if(this.optionDataSet){
            this.initList();
            this.rendered = true;
        }       
    },  
	getRenderText : function(record){
        if(!record) return '';
        var rder = $S.getFunction(this.displayRenderer),
            text = '&#160;';
        if(rder){
            text = rder.call(window,record);
        }else{
            text = record.get(this.displayField);
        }
		return text;
	},
	refresh:function(){
		this.view.update('');
        this.selectIndex = null;
		this.currentIndex = null;
	},
    highlightItem:function(idx1,idx2,cls){
        if(Ext.isEmpty(idx1)) return;
        if(idx1 != idx2) {
            var cn = this.getNode(idx2),tn = this.getNode(idx1);
            if(tn){
                if(cn)Ext.fly(cn).removeClass(cls);
                Ext.fly(tn).addClass(cls);                
                return true;
            }
            return false;
        }
    },
    clearSelectItem: function(){
        var sn = this.getNode(this.selectIndex);
        if(sn)Ext.fly(sn).removeClass(this.selectedClass);
        var cn = this.getNode(this.currentIndex);
        if(cn)Ext.fly(cn).removeClass(this.overClass);
        this.selectIndex = null;
        this.currentIndex = null;
        this.popup.scrollTo('top',0);
    },
	selectItem:function(index){
        if(this.highlightItem(index,this.selectIndex,this.selectedClass)){
            this.selectIndex = index;
            this.doFocusRow(index);
        }
	},
    overItem : function(index,focus){
        if(this.highlightItem(index,this.currentIndex,this.overClass)){
            this.currentIndex = index;
            if(focus) this.doFocusRow(index);
        }
    },
    doFocusRow : function(row){
        var r = 22,
            ub = this.popup,
            stop = ub.getScroll().top,
            h = ub.getHeight(),
            sh = ub.dom.scrollWidth > ub.dom.clientWidth? 16 : 0;
        if(row*r<stop){
            ub.scrollTo('top',row*r-1)
        }else if((row+1)*r>(stop+h-sh)){//this.ub.dom.scrollHeight
            ub.scrollTo('top', (row+1)*r-h + sh);
        }
    },
	getNode:function(index){		
		return this.view.dom.childNodes[index];
	},	
	destroy : function(){
    	$S.ComboBox.superclass.destroy.call(this);
		delete this.view;
	},
	getText : function() {		
		return this.text;
	},
    processValue : function(rv){
        return  this.getRecordByDisplay(rv) ? rv : '';
    },
    setValue: function(v, silent){
        $S.ComboBox.superclass.setValue.call(this, v, silent);
        if(this.record){
            var field = this.record.getField(this.binder.name);
            if(field && !silent){
                var mapping = field.get('mapping'),raw = this.getRawValue(),record = this.getRecordByDisplay(raw);
                if(mapping){
                    for(var i=0;i<mapping.length;i++){
                        var map = mapping[i],vl = record ? record.get(map.from) : '';
                        if(map.from == this.displayField) continue;//上面已经setValue过,防止有displayRenderer的时候被重新覆盖掉
                        if(!Ext.isEmpty(vl,true)){
                            this.record.set(map.to,vl);
                        }else{
                            delete this.record.data[map.to];
                        }
                        
                    }
                }
            }
        }
    },
	getIndex:function(v){
		var datas = this.optionDataSet.getAll(), l = datas.length;
		for (var i = 0; i < l; i++) {
			if (this.getRenderText(datas[i]) == v) {
				return i;
			}
		}
        return -1;
	},
	onViewClick:function(e,t){
		if(t.tagName=='LI'){
		    this.selectRow(Ext.fly(t).getAttributeNS("","code"));
            this.collapse();
            this.focus();
		}
	},
	onViewMove:function(e,t){
        if(t.tagName=='LI'){
            var ods = this.optionDataSet, r = ods.find(this.valueField,Ext.fly(t).getAttributeNS("","code"));
            if(r){
                this.overItem(ods.indexOf(r));
            }
        }    
	},
	selectRow:function(v){
		if(!v)return;
        var r = this.optionDataSet.find(this.valueField,v),t = this.getRenderText(r);
        this.fireEvent('select',this, v,t,r);
        this.setValue(t);
	},
//    processValue : function(rv){
//        var r = this.getRecordByDisplay(rv);
//        if (r != null) {
//            return r.get(this.valueField);
//        } else {
//            return '';
//        }
//    },
//    onBlur : function(e) {
//        $S.ComboBox.superclass.onBlur.call(this, e);
//        if (this.isFocused && !this.isExpanded) {// TODO:grid离开编辑器会触发两次?
//            var raw = this.getRawValue();
//            var record = this.getRecordByDisplay(raw);
//            if (record != null) {
//                this.setValue(record.get(this.displayField));
//            } else {
//                this.setValue('');
//            }
//        }
//    },    
	onDataSetLoad: function(){
		this.rendered = false;
		if(this.isExpanded) {
            this.expand();
		}
	},  
    onKeyUp : function(e){
        if(this.disabled|| this.editable === false)return;
        var c = e.keyCode;
        if(!e.isSpecialKey()){
            this.doQuery(this.getRawValue());
            if(!this.isExpanded) {
                $S.ComboBox.superclass.expand.call(this);
            } else {
                this.syncPopup();
            }
            this.rendered = false;
        }
        $S.ComboBox.superclass.onKeyUp.call(this, e);
    },
    onKeyDown: function(e){
        if(this.disabled)return;
        var current = Ext.isEmpty(this.currentIndex) ? -1 : this.currentIndex,
            keyCode = e.keyCode;
        if(this.isExpanded && (keyCode == 40||keyCode == 38)) {// 38-UP  40-DOWN
            if(keyCode == 38){
                current --;
                if(current>=0){
                    this.overItem(current,true)
                }            
            }
            if(keyCode == 40){
                current ++;
                if(current<this.view.dom.childNodes.length){
                    this.overItem(current,true)
                }
            }
        } else if(this.isExpanded && keyCode == 13){//13-ENTER
            if(current==-1){
                this.collapse();
                return;
            }else {
                this.selectItem(current);
                this.selectRow(Ext.fly(this.getNode(current)).getAttributeNS("","code"));
            }
        }
        $S.ComboBox.superclass.onKeyDown.call(this,e);
    }    
});